package kr.ac.inha.biselab.biomonitor;

import gnu.io.*;

import java.io.*;
import java.util.*;

import org.eclipse.swt.widgets.Combo;

public class Communicator implements SerialPortEventListener {

	/* Serial Communication */
	private Enumeration ports = null;
	private static HashMap  portMap = new HashMap();
	private CommPortIdentifier selectedPortIdentifier = null;
	private String logText = "";
	private SerialPort serialPort = null;
	private InputStream input = null;
	public InputStream getInput() {
		return input;
	}

	public void setInput(InputStream input) {
		this.input = input;
	}

	private OutputStream output = null;
	
	public OutputStream getOutput() {
		return output;
	}

	public void setOutput(OutputStream output) {
		this.output = output;
	}

	private boolean connected = false;
	private boolean drawGraph = false;
	final static int TIMEOUT = 2000;
	final static int SPACE_ASCII = 32;
	final static int DASH_ASCII = 45;
	final static int NEU_LINE_ASCII = 10;
	



	Queue<Byte> queue = new LinkedList<Byte>();
	public Communicator() {
	}

	@Override
	public void serialEvent(SerialPortEvent arg0) {
		byte[] data = new byte[128];
		int len;
		
		int i;
		if(arg0.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			/*
			try {
				len = input.read(data);
				for(i = 0 ; i < len ; i++) {
					queue.offer(data[i]);
				}
			} catch (IOException e) {
				
			}
		*/
		}
		
	}

	public Queue<Byte> getQueue() {
		return queue;
	}

	public void setQueue(Queue<Byte> queue) {
		this.queue = queue;
	}

	public boolean isConnected() {
		return connected;
	}

	public  void setConnected(boolean connected) {
		this.connected = connected;
	}

	public boolean isDrawGraph() {
		return drawGraph;
	}

	public void setDrawGraph(boolean drawGraph) {
		this.drawGraph = drawGraph;
	}
	public void searchForPorts() {
		ports = CommPortIdentifier.getPortIdentifiers();
		
		while(ports.hasMoreElements()) {
			CommPortIdentifier curPort = (CommPortIdentifier)ports.nextElement();
			
			// get only serial port
			if(curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				BioMonitorMain.getComboCOMPort().add(curPort.getName());
				BioMonitorMain.getComboCOMPort().select(BioMonitorMain.getComboCOMPort().getItemCount() - 1);
				BioMonitorMain.getComboComPort2().add(curPort.getName());
				BioMonitorMain.getComboComPort2().select(BioMonitorMain.getComboCOMPort().getItemCount() - 1);
				portMap.put(curPort.getName(), curPort);
			}
		}
	}
	
	public void connect(String port, int baudRate, String name) {
		String selectedPort = port;
		this.selectedPortIdentifier = (CommPortIdentifier)portMap.get(selectedPort);
	
		CommPort commPort = null;
		
		try {
			commPort = selectedPortIdentifier.open(name, TIMEOUT);
			
			serialPort = (SerialPort)commPort;
			serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			setConnected(true);
			
			logText = selectedPort + " Opened Successfully.";
			BioMonitorMain.getTextUartLog().append(logText + "\n");
		} catch(PortInUseException e) {
			logText = selectedPort + " is in use. (" + e.toString() + ")";
			BioMonitorMain.getTextUartLog().append(logText +"\n");
		} catch(Exception e) {
			logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
			BioMonitorMain.getTextUartLog().append(logText+"\n");
		}
	
		
	}

	public boolean initIoStream() {
		boolean successful = false;
		try {
			this.input = serialPort.getInputStream();
			this.output = serialPort.getOutputStream();
			
			successful = true;
			return successful;
		} catch (IOException e) {
			e.printStackTrace();
			logText = "I/O Stream failed to open. (" + e.toString() + ")";
			BioMonitorMain.getTextUartLog().append(logText + "\n");
			return successful;
		}
	}
	
	public void initListener() throws TooManyListenersException {
		try {
			serialPort.addEventListener(this);
			serialPort.notifyOnDataAvailable(true);
		} catch (TooManyListenersException e) {
			logText = "Too many listeners. (" + e.toString() + ")";
			BioMonitorMain.getTextUartLog().append(logText+"\n");
		}
		
	}
	public void disconnect() {
		try {
			serialPort.removeEventListener();
			serialPort.close();
			input.close();
			output.close();
			setConnected(false);
			
			logText = "Disconnected.";
			BioMonitorMain.getTextUartLog().append(logText + "\n");
		} catch (Exception e) {
			logText = "Failed to close " + serialPort.getName() + "(" + e.toString() + ")";
			BioMonitorMain.getTextUartLog().append(logText + "\n");
		}
	}
	
	public void write(char data) {
		try {
			output.write(data);
			output.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void write(char[] data) {
		int i;
		int len = data.length;
		for(i = 0 ; i < len ; i++) {
			try {
				output.write(data[i]);
				output.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
